#if !defined( CONSTRUCTOR_FAILURE_H_INCLUDED )
#define CONSTRUCTOR_FAILURE_H_INCLUDED

#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000

#include <stdexcept>
#include <string>
#include <typeinfo>

#include "format_string.h"

/////////////////////////////////////////////////////////////////////////////
template < typename t_whatever, typename t_base = std::runtime_error >
class t_constructor_failure : public t_base
{
public:
	// Constructors
	t_constructor_failure() : t_base( build_msg() ) {}
	explicit t_constructor_failure( std::string const & msg ) : t_base( build_msg( msg ) ) {}

private:
	// Member functions
	static std::string build_msg();
	static std::string build_msg( std::string const & msg );
};

#if defined( NDEBUG )

/////////////////////////////////////////////////////////////////////////////
template < typename t_whatever, typename t_base >
inline std::string t_constructor_failure< t_whatever, t_base >::build_msg()
{
	return std::string();
}

/////////////////////////////////////////////////////////////////////////////
template < typename t_whatever, typename t_base >
inline std::string t_constructor_failure< t_whatever, t_base >::build_msg( std::string const & msg )
{
	return msg;
}

#else // defined( NDEBUG )

/////////////////////////////////////////////////////////////////////////////
template < typename t_whatever, typename t_base >
inline std::string t_constructor_failure< t_whatever, t_base >::build_msg()
{
	return build_msg( std::string() );
}

/////////////////////////////////////////////////////////////////////////////
template < typename t_whatever, typename t_base >
std::string t_constructor_failure< t_whatever, t_base >::build_msg( std::string const & msg )
{
	if ( msg.size() == 0 )
		return format_string( "Failed to construct %s", typeid( t_whatever ).name() );

	return format_string( "Failed to construct %s: %s", typeid( t_whatever ).name(), msg.c_str() );
}

#endif // defined( NDEBUG )

#endif // !defined( CONSTRUCTOR_FAILURE_H_INCLUDED )
